
#include "TinyMsgHeader.h"


namespace TinyCC{
	namespace msg{



		void CTinyMetaElementSet::serialize(const char* data,long &length)
		{
			long maxLength=length;

			char* p=(char*)data;
			length=0;

			//Take one WORD to store the count of medadata
			long metaValueNumber=static_cast<long>(m_elementSetValueList.size());
			memcpy(p,&metaValueNumber,sizeof(WORD));
			p=p+sizeof(WORD);
			_incLength(length,sizeof(WORD),maxLength);

			//Copy each metadata
			long valueLength=0;
			CTinyMetaElement* pMValue=m_elementSetKey;

			//copy key
			if(pMValue!=NULL)
			{
				pMValue->serialize(p,valueLength);
				p=p+valueLength;
				_incLength(length,valueLength,maxLength);
				valueLength=0;
			}

			//copy value
			std::list<CTinyMetaElement*>::iterator itEnumMValue=m_elementSetValueList.begin();
			while(itEnumMValue!=m_elementSetValueList.end())
			{
				pMValue=*itEnumMValue;
				if(pMValue!=NULL)
				{
					pMValue->serialize(p,valueLength);
					p=p+valueLength;
					_incLength(length,valueLength,maxLength);
					valueLength=0;
				}
				itEnumMValue++;
			}//while
			if(length>m_serializeSize)
			{
				length=0;
			}
		}
		bool CTinyMetaElementSet::deSerialize(char *pMsg,long valueNumber,long& dwLength)
		{
			char* p=pMsg;
			dwLength=0;
			DWORD* pDWord=NULL;
			size_t dwordSize=sizeof(DWORD);
			for(int i=1;i<=valueNumber;i++)
			{
				pDWord=(DWORD*)p;
				p=p+dwordSize;
				dwLength += (long)( dwordSize );
				if( dwLength > 65535 )
					return false;

				if( *pDWord > 65535 )
					return false;
				CTinyMetaElement* pMValue=new CTinyMetaElement(p,*pDWord);
				if(pMValue==NULL)
					return false;
				p=p+*pDWord;
				dwLength+=*pDWord;

				/*if(i==1)
				{
					m_elementSetKey=pMValue;
				}
				else*/
					m_elementSetValueList.push_back(pMValue);
			}//for

			m_serializeSize+=dwLength;

			return true;
		}


		//new a CTinyMetaElement object before pushParam as key and value !!!
		long CTinyParamMap::pushParam(CTinyMetaElement* key,CTinyMetaElement* value)
		{
			//Check if named parameter exists
			CTinyMetaElementSet* pMVCluster=NULL;
			std::map< std::string, CTinyMetaElementSet* >::iterator itEnummetaValue=m_namedParamList.find(key->getData());
			if(itEnummetaValue!=m_namedParamList.end())
			{
				pMVCluster=itEnummetaValue->second;
				if(pMVCluster->isKeyEqual(key))
				{
					return pMVCluster->pushValue(value);
				}//if
				itEnummetaValue++;
			}//if

			//no named parameter 
			pMVCluster=new CTinyMetaElementSet(key);
			if(pMVCluster==NULL)
				return -1;
			m_namedParamList.insert( std::pair< std::string,CTinyMetaElementSet* >(key->getData(),pMVCluster));
			return pMVCluster->pushValue(value);

		}

		CTinyMetaElement* CTinyParamMap::getParamKey(int namedParamIndex)
		{
			if(namedParamIndex < 0)
				return NULL;

			std::map< std::string,CTinyMetaElementSet* >::iterator itFindMValue=m_namedParamList.begin();
			while(itFindMValue!=m_namedParamList.end())
			{
				
				if(namedParamIndex==0)
				{
					CTinyMetaElementSet* pMValue=itFindMValue->second;
					if(pMValue!=NULL)
					{
						return pMValue->getKey();
					}
				}//if
				namedParamIndex--;
				itFindMValue++;
			}//while

			return NULL;

		}

		int CTinyParamMap::getParamValueCount(CTinyMetaElement* key)
		{
			CTinyMetaElementSet* pMValue=NULL;
			std::map< std::string,CTinyMetaElementSet* >::iterator itFindMValue=m_namedParamList.begin();
			while(itFindMValue!=m_namedParamList.end())
			{
				pMValue=itFindMValue->second;
				if(pMValue!=NULL)
				{
					if(pMValue->isKeyEqual(key))
					{
						return (pMValue->getValueCount());
					}
				}//if
				itFindMValue++;
			}//while

			return 0;
		}

		int CTinyParamMap::getParamValueCount(int keyIndex)
		{
			CTinyMetaElementSet* pMValue=NULL;
			std::map< std::string,CTinyMetaElementSet* >::iterator itFindMValue=m_namedParamList.begin();
			while(itFindMValue!=m_namedParamList.end())
			{
				keyIndex--;
				if(keyIndex==0){
					pMValue=itFindMValue->second;
					if(pMValue!=NULL)
					{
						return (pMValue->getValueCount()-1);
					}//if
				}
				itFindMValue++;
			}//while

			return 0;
		}

		CTinyMetaElement* CTinyParamMap::getParamValue(CTinyMetaElement* key,int ParamValueIndex)
		{

			if(key == NULL || key->getDataLength() <= 0 )
				return NULL;

			CTinyMetaElementSet* pMValueCluster=NULL;
			std::map< std::string,CTinyMetaElementSet* >::iterator itFindMValueCluster=m_namedParamList.begin();
			while(itFindMValueCluster!=m_namedParamList.end())
			{
				pMValueCluster=itFindMValueCluster->second;
				if(pMValueCluster!=NULL)
				{
					if(pMValueCluster->isKeyEqual(key))
					{
						return pMValueCluster->getValue(ParamValueIndex);
					}
				}//if
				itFindMValueCluster++;
			}//while

			return NULL;
		}

		CTinyMetaElement* CTinyParamMap::getParamValue(int keyIndex, int ParamValueIndex)
		{

			CTinyMetaElementSet* pMValueCluster=NULL;
			std::map< std::string,CTinyMetaElementSet* >::iterator itFindMValueCluster=m_namedParamList.begin();
			while(itFindMValueCluster!=m_namedParamList.end())
			{
				keyIndex--;
				if(keyIndex==0)
				{
					pMValueCluster=itFindMValueCluster->second;
					if(pMValueCluster!=NULL)
					{
						return pMValueCluster->getValue(ParamValueIndex);
					}//if
				}
				itFindMValueCluster++;
			}//while

			return NULL;
		}

		void CTinyParamMap::serialize(const char* data,long &length)
		{
			long maxLength=length;
			length=0;
			char* p=(char*)data;
			//Take on WORD to store reference index of named parameter cluster
			memcpy(p,&m_EPIndex,sizeof(WORD));
			p=p+sizeof(WORD);
			_incLength(length,sizeof(WORD),maxLength);

			//Take on WORD to sotre the count of named parameter
			long paramNumber=(long/* added for warning*/)m_namedParamList.size();
			memcpy(p,&paramNumber,sizeof(WORD));
			p=p+sizeof(WORD);
			_incLength(length,sizeof(WORD),maxLength);

			//Copy each metaValue cluster
			long clusterLength=0;
			CTinyMetaElementSet* pMVCluster=NULL;
			std::map< std::string,CTinyMetaElementSet* >::iterator itEnumMVCluster=m_namedParamList.begin();
			while(itEnumMVCluster!=m_namedParamList.end())
			{
				pMVCluster=itEnumMVCluster->second;
				if(pMVCluster!=NULL)
				{
					clusterLength=maxLength-length;
					pMVCluster->serialize(p,clusterLength);
					p=p+clusterLength;
					_incLength(length,clusterLength,maxLength);
					clusterLength=0;
				}//if
				itEnumMVCluster++;
			}//while
		}

		bool CTinyParamMap::deSerialize(char *pMsg,long& length)
		{
			length=0;
			char* p=pMsg;

			WORD* pWord=NULL;
			DWORD* pDWord=NULL;

			//Get the count of named paraemter
			pWord=(WORD*)p;
			p=p+sizeof(WORD);
			length+=sizeof(WORD);
			WORD npNumber=*pWord;

			for(WORD i=1;i<=npNumber;i++)
			{
				//Get the count of paramter value
				pWord=(WORD*)p;
				p=p+sizeof(WORD);
				length+=sizeof(WORD);
				WORD npValueNumber=*pWord;

				//Get the KEY of named parameter
				//Get the length of KEY
				pDWord=(DWORD*)p;
				p=p+sizeof(DWORD);
				length+=sizeof(DWORD);
				if(*pDWord>10240)
					return false;
				std::string key(p,*pDWord);

				CTinyMetaElement * key2=new CTinyMetaElement(p,*pDWord);

				CTinyMetaElementSet* pMVCluster=new CTinyMetaElementSet(key2);
				if(pMVCluster==NULL)
					return false;
				p=p+*pDWord;
				length+=*pDWord;
				long valueLength=0;//the length of serialized message return from pMVCluster->deSerialize
				if(!pMVCluster->deSerialize(p,npValueNumber,valueLength))
				{
					delete pMVCluster;
					return false;
				}
				p=p+valueLength;
				length+=valueLength;

				m_namedParamList.insert( std::pair< std::string,CTinyMetaElementSet* >( key, pMVCluster) );
			}//for j

			return true;
		}

		long CTinyParamMap::getSerializeSize()
		{	
			long serializeSize=2*sizeof(WORD);/*Take one WORD to store reference index,Take one WORD to store the count of named paraemter*/
			CTinyMetaElementSet* pMVCluster=NULL;
			std::map< std::string,CTinyMetaElementSet* >::iterator itEnumMVCluster=m_namedParamList.begin();
			while(itEnumMVCluster!=m_namedParamList.end())
			{
				pMVCluster=itEnumMVCluster->second;
				if(pMVCluster!=NULL)
					serializeSize+=pMVCluster->getSerializeSize();
				itEnumMVCluster++;
			}//while
			return serializeSize;	
		}
	}
}